/* Yet Another Experimental Software Renderer
 *
 * Copyright (c) 2010 Pawel "Hery" Dziepak
 */

#include "engine.h"

using namespace yaesr;

void engine_state::change_status(eng_state new_state) {
	switch (new_state) {
		case initialized :
			Error("Cannot chage engine state to \"initialized\"");

		case configuring :
			if (state == initialized || state == standby) {
				state = configuring;
				return;
			} else
				Error("Cannot chage engine state to \"configuring\"");

		case configured:
			if (state == configuring) {
				state = configured;
				return;
			} else
				Error("Cannot chage engine state to \"configured\"");

		case standby:
			if (state == configured || state == rendering) {
				state = standby;
				return;
			} else
				Error("Cannot chage engine state to \"standby\"");

		case rendering:
			if (state == configured || state == standby) {
				state = rendering;
				return;
			} else
				Error("Cannot chage engine state to \"rendering\"");

		case destroying:
			state = destroying;
			return;

		default:
			Error("Attempt to switch to unknown engine state");
	}
}
		
engine::engine() : prev(NULL), pp(new pipeline) {
	state.change_status(engine_state::configuring);

	output_merger *omerg = new default_om;
	pp->set_output_merger(omerg);

	rasterizer *rast = new default_rasterizer(omerg);
	pp->set_rasterizer(rast);

	pp->set_input_assembler(new default_ia(rast));
}

void engine::set_output(pixel_output *po) {
	Assert(po != NULL);

	pp->set_output(po);

	if (!state.is_status(engine_state::configuring))
		pp->launch();
}

void engine::set_vertex_shader(vertex_shader *vs) {
	Assert(vs != NULL);

	pp->set_vertex_shader(vs);

	if (!state.is_status(engine_state::configuring))
		pp->launch();
}

void engine::set_geometry_shader(geometry_shader *gs) {
	Assert(gs != NULL);

	pp->set_geometry_shader(gs);

	if (!state.is_status(engine_state::configuring))
		pp->launch();
}

void engine::set_pixel_shader(pixel_shader *ps) {
	Assert(ps != NULL);

	pp->set_pixel_shader(ps);

	if (!state.is_status(engine_state::configuring))
		pp->launch();
}

void engine::launch() {
	state.change_status(engine_state::configured);
	pp->launch();
}
